﻿using System;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;

namespace ZilLion.Service.Core.MongoDbManager.ObjectDb
{
    public class ObjectDbRepository : MongoDbRepository, IObjectDbRepository
    {
        public ObjectDbRepository()
        {
        }

        public ObjectDbRepository(string DatabaseName, string RootName)
        {
            Context.DatabaseName = DatabaseName;
            Context.RootName = RootName;
        }

        public MongoServer MongoServer { get; set; }

        public void SaveObjectToMongoDb<T>(T item)
        {
            if (MongoServer == null) return;
            var db = MongoServer.GetDatabase(Context.DatabaseName);
            var collection = db.GetCollection(Context.RootName);
            collection.Insert(item);
        }


        /// <summary>
        ///     添加
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void Insert<T>(T model) where T : IMongoModel
        {
            model.created_at = new BsonDateTime(DateTime.Now);
            model.updated_at = new BsonDateTime(DateTime.Now);
            if (MongoServer == null) InitGridFs();
            var db = MongoServer.GetDatabase(Context.DatabaseName);
            var collection = db.GetCollection(Context.RootName);
            collection.Insert(model);
        }

        /// <summary>
        ///     添加
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool InsertWithexpire<T>(T model, TimeSpan expire) where T : IMongoModel
        {
            model.created_at = new BsonDateTime(DateTime.Now);
            model.updated_at = new BsonDateTime(DateTime.Now);
            if (MongoServer == null) InitGridFs();
            var keys = IndexKeys.Descending("updated_at");
            var options = IndexOptions.SetTimeToLive(expire);
            var db = MongoServer.GetDatabase(Context.DatabaseName);
            var collection = db.GetCollection(Context.RootName);
            collection.CreateIndex(keys, options);
            var res = collection.Insert(model);
            return !res.HasLastErrorMessage;
            //return res.Upserted.AsBoolean;
        }

        /// <summary>
        ///     删除
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool Delete<T>(T model) where T : IMongoModel
        {
            if (MongoServer == null) InitGridFs();
            var db = MongoServer.GetDatabase(Context.DatabaseName);
            var collection = db.GetCollection(Context.RootName);
            var res = collection.Remove(Query.EQ("_id", model.id));
            return res.DocumentsAffected > 0;
        }

        /// <summary>
        ///     查找
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public Q Find<Q>(IMongoQuery query) where Q : class
        {
            var db = MongoServer.GetDatabase(Context.DatabaseName);
            var collection = db.GetCollection(Context.RootName);
            return collection.FindOne(query).As<Q>();
        }

        /// <summary>
        ///     查找
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public MongoCursor<BsonDocument> FindAll(IMongoQuery query)
        {
            if (MongoServer == null) InitGridFs();
            var db = MongoServer.GetDatabase(Context.DatabaseName);
            var collection = db.GetCollection(Context.RootName);
            var ts = collection.Find(query);
            return ts;
        }


        /// <summary>
        ///     修改
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public long Update<T>(T model) where T : IMongoModel
        {
            if (MongoServer == null) InitGridFs();
            model.updated_at = new BsonDateTime(DateTime.Now);
            var db = MongoServer.GetDatabase(Context.DatabaseName);
            var collection = db.GetCollection(Context.RootName);
            var doc = BsonExtensionMethods.ToBsonDocument(model);
            var res = collection.Update(Query.EQ("_id", model.id), new UpdateDocument(doc));
            return res.DocumentsAffected;
        }


        public void InitGridFs()
        {
            if (Context != null)
            {
                MongoServerSettings settings = null;
                MongoServerAddress mongoServerAddress;
                if (!Context.ServerConnectString.Contains("@"))
                {
                    if (MongoServerAddress.TryParse(Context.ServerConnectString, out mongoServerAddress))
                        settings = new MongoServerSettings
                        {
                            Server = mongoServerAddress,
                            MaxConnectionPoolSize = 500, //最大连接池数量
                            WaitQueueSize = 10 //等待列队数量
                        };
                }
                else
                {
                    var Url = string.Format("mongodb://{0}", Context.ServerConnectString);
                    var url = new MongoUrl(Url);
                    settings = MongoServerSettings.FromUrl(url);
                    settings.MaxConnectionPoolSize = 500;
                    settings.WaitQueueSize = 10;
                }
                if (settings != null)
                    MongoServer = new MongoServer(settings);
            }
        }
    }
}